/*!
 * ZUI - v1.4.0 - 2016-01-26
 * http://zui.sexy
 * GitHub: https://github.com/easysoft/zui.git 
 * Copyright (c) 2016 cnezsoft.com; Licensed MIT
 */

/* ========================================================================
 * ZUI: calendar.js
 * http://zui.sexy
 * ========================================================================
 * Copyright (c) 2014 cnezsoft.com; Licensed MIT
 * ======================================================================== */
(function ($, window){
    'use strict';
    var name = 'zui.calendar';
    var NUMBER_TYPE_NAME = 'number';
    var STRING_TYPE_NAME = 'string';
    var OBJECT_TYPE_NAME = 'object';
    var UNDEFINED_TYPE_NAME = 'undefined';
    var presetColors = {
        "primary": 1,
        "green": 2,
        "red": 3,
        "blue": 4,
        "yellow": 5,
        "brown": 6,
        "purple": 7
    };

    var getNearbyLastWeekDay = function (date, lastWeek) {
        lastWeek = lastWeek || 1;

        var d = date.clone();
            while(d.getDay() != lastWeek) {
            d.addDays(-1);
        }
        d.clearTime();
        return d;
    },
    getFirstDayOfMonth = function (date) {
        var d = date.clone();
        d.setDate(1);
        return d;
    },
    calculateDays = function (start, end) {
        var s = start.clone().clearTime();
        var e = end.clone().clearTime();
        return Math.round((e.getTime() - s.getTime()) / Date.ONEDAY_TICKS) + 1;
    },
    everyDayTo = function (start, end, callback) {
        var a = start.clone();
        var i = 0;
        while (a <= end) {
            callback(a.clone(), i++);
            a.addDays(1);
        }
    },
    getLastDayOfMonth = function (date) {
        var d = date.clone();
        var month = d.getMonth();
        d.setDate(28);
        while (d.getMonth() == month) {
            d.addDays(1);
        }
        d.addDays(-1);
        return d;
    };

    var Calendar = function (element, options) {
        this.name = name;
        this.$ = $(element);
        this.id = this.$.attr('id') || (name + $.zui.uuid());
        this.$.attr('id', this.id);
        this.storeName = name + '.' + this.id;

        this.getOptions(options);
        this.getLang();

        this.data = this.options.data;
        this.addCalendars(this.data.calendars);
        this.addEvents(this.data.events);
        this.sortEvents();
        this.storeData = $.zui.store.pageGet(this.storeName, {
            date: 'today',
            view: 'month'
        });

        this.date = this.options.startDate || 'today';
        this.view = this.options.startView || 'month';
        //添加当前事件类型，默认为以时间为准，可选以天为单位
        this.eventType = this.options.eventType || 'time';
        this.date = 'today';

        this.$.toggleClass('limit-event-title', options.limitEventTitle);

        if(this.options.withHeader) {
            var $header = this.$.children('.calender-header');
            if(!$header.length) {
                $header = $('<header><div class="btn-toolbar"><div class="btn-group"><button type="button" class="btn btn-today">{today}</button></div><div class="btn-group"><button type="button" class="btn btn-prev"><i class="icon icon-chevron-left"></i></button><button type="button" class="btn btn-next"><i class="icon icon-chevron-right"></i></button></div><div class="btn-group"><span class="calendar-caption"></span></div></div></header>'.format(this.lang));
                this.$.append($header);
            }
            this.$caption = $header.find('.calendar-caption');
            this.$todayBtn = $header.find('.btn-today');
            this.$header = $header;
        }

        var $views = this.$.children('.calendar-views');
        if(!$views.length) {
            $views = $('<div class="calendar-views"></div>');
            this.$.append($views);
        }
        this.$views = $views;
        this.$monthView = $views.children('.calendar-view.month');

        this.display();

        this.bindEvents();
    };

    // default options
    Calendar.DEFAULTS = {
        lang: 'en_us',
        langs: {
            'zh_cn': {
                weekNames: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
                monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
                today: '今天',
                year: '{0}年',
                month: '{0}月',
                yearMonth: '{0}年{1}月'
            },
            'zh_tw': {
                weekNames: ['週一', '週二', '週三', '週四', '週五', '週六', '週日'],
                monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
                today: '今天',
                year: '{0}年',
                month: '{0}月',
                yearMonth: '{0}年{1}月'
            },
            'en_us': {
                weekNames: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
                monthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                today: 'Today',
                year: '{0}',
                month: '{0}',
                yearMonth: '{2}, {0}'
            }
        },
        data: {
            calendars: {
                defaultCal: {
                    color: '#229F24'
                }
            },
            events: []
        },
        // startView: "month",      // default view when load complete
        // startDate: 'today',      // default date when load complete
        showOtherMonth: false,      //是否显示其它月份
        cacheView: false,           //是否缓存视图
        limitEventTitle: true,
        storage: true,
        withHeader: true,
        dragThenDrop: true          // drag an event and drop at another day
    };

    /**
     * 根据开始时间对事件进行排序
     * @returns {undefined}
     */
    Calendar.prototype.sortEvents = function () {
        var events = this.events;
        if (!$.isArray(events)) {
            events = [];
        }

        events.sort(function (a, b) {
            return a.start > b.start ? 1 : (a.start < b.start ? (-1) : 0);
        });
    };
    /**
     * 下一月
     * @returns {undefined}
     */
    Calendar.prototype.next = function () {
        var self = this;
        if (self.view === 'month') {
            self.date.addMonths(1);
        }
        self.display();
        self.callEvent('clickNextBtn', {
            element: self,
            year: self.date.getFullYear(),
            month: self.date.getMonth() + 1,
            day: self.date.getDay()
        });
    };
    /**
     * 上一月
     * @returns {undefined}
     */
    Calendar.prototype.prev = function () {
        var self = this;
        if (self.view === 'month') {
            self.date.addMonths(-1);
        }
        self.display();
        self.callEvent('clickPrevBtn', {
            element: self,
            year: self.date.getFullYear(),
            month: self.date.getMonth() + 1,
            day: self.date.getDay()
        });
    };
    /**
     * 绑定一些系统按钮的点击事件
     * @returns {undefined}
     */
    Calendar.prototype.bindEvents = function () {
        var $e = this.$,
                self = this;
        //事件处理
        $e.on('click', '.btn-today', function () {    //点击了今天按钮
            self.date = new Date();
            self.display();
            self.callEvent('clickTodayBtn');
        }).on('click', '.btn-next', function () {     //点击了下一个按钮
            var param = {
                element: self,
                year: self.date.getFullYear(),
                month: self.date.getMonth() + 1,
                day: self.date.getDay(),
                result: {status: true}
            };
            self.callEvent('clickNextBtnBefore', param);
            var result = param.result;
            if (!result.status) {
                layer.confirm(result.info, function (index) {
                    layer.close(index);
                    self.next();
                }, function (index) {
                    layer.close(index);
                    return;
                });
            } else {
                if (result.info)
                    toastr.info(result.info);
                self.next();
            }
        }).on('click', '.btn-prev', function ()      //点击了上一个按钮
        {
            var param = {
                element: self,
                year: self.date.getFullYear(),
                month: self.date.getMonth() + 1,
                day: self.date.getDay(),
                result: {status: true}
            };
            self.callEvent('clickPrevBtnBefore', param);
            var result = param.result;
            if (!result.status) {
                layer.confirm(result.info, function (index) {
                    layer.close(index);
                    self.prev();
                }, function (index) {
                    layer.close(index);
                    return;
                });
            } else {
                if (result.info)
                    toastr.info(result.info);
                self.prev();
            }
        }).on('click', '.event', function(event) {   //单击了某个事件
            self.callEvent('clickEvent', {
                element: this,
                event: $(this).data('event'),
                events: self.events
            });
            event.stopPropagation();
        }).on('click', '.cell-day', function() {     //单击了某个日子
            if (!self.options.showOtherMonth) {
                var thisDate = new Date($(this).children('.day').attr('data-date'));
                //console.log(self.date.getMonth() + ',' + thisDate.getMonth());
            }
            self.callEvent('clickCell', {
                element: this,
                view: self.view,
                date: new Date($(this).children('.day').attr('data-date')),
                events: self.events
            });
        });
    };
    /**
     * 添加日历
     * @param {type} calendars
     * @param {type} silence
     * @returns {undefined}
     */
    Calendar.prototype.addCalendars = function (calendars, silence) {
        var that = this;
        if(!that.calendars) that.calendars = {};

        if ($.isPlainObject(calendars)) {
            calendars = [calendars];
        }
        $.each(calendars, function (index, cal) {
            if(!silence && !that.callEvent('beforeAddCalendars', {
                    newCalendar: cal,
                    data: that.data
                })) {
                return;
            }

            if(!cal.color) cal.color = 'primary';
            if (!presetColors[cal.color.toLowerCase()]) {
                var c = new $.zui.Color(cal.color);
                cal.textColor = c.contrast().hexStr();
            } else {
                cal.presetColor = true;
            }
            that.calendars[cal.name] = cal;
        });

        if (!silence) {
            that.display();
            that.callEvent('addCalendars', {
                newCalendars: calendars,
                data: that.data
            });
        }
    };
    /**
     * 添加事件
     * @param {type} events
     * @param boolean silence 如果为真，则需要对添加的事件进行一些判断
     * @returns {undefined}
     */
    Calendar.prototype.addEvents = function(events, silence) {
        var that = this;
        if(!that.events) that.events = [];

        if($.isPlainObject(events)) {
            events = [events];
        }
        $.each(events, function(index, e) {
            if(!silence && !that.callEvent('beforeAddEvent', {
                    newEvent: e,
                    data: that.data
                })) {
                return;
            }

            var startType = typeof e.start;
            var endType = typeof e.end;
            if(startType === NUMBER_TYPE_NAME || startType === STRING_TYPE_NAME) {
                e.start = new Date(e.start);
            }
            if(endType === NUMBER_TYPE_NAME || endType === STRING_TYPE_NAME) {
                e.end = new Date(e.end);
            }
            if(typeof e.id === UNDEFINED_TYPE_NAME) {
                e.id = $.zui.uuid();
            }
            //根据事件类型来确定，强制性的。
            if (e.allDay || that.options.eventType == 'day') {
                e.allDay = true;
                e.start.clearTime();
            }

            //生成日期
            e.year = e.start.getFullYear();
            e.month = e.start.getMonth() + 1;
            e.day = e.start.getDate();
            if (e.days) {
                e.end = e.start.clone();
                e.end = new Date(e.end.setDate(e.end.getDate() + e.days));
            } else {
                if (e.allDay)
                    e.end.clearTime().addDays(1).addMilliseconds(-1);
                e.days = calculateDays(e.start, e.end);
            }
            if (e.days > 1) {
                for (var i = 1; i <= e.days; i++) {
                    var f = e;
                    f = $.extend({}, f, {
                        allDay: e.allDay,
                        color: e.color,
                        days: 1,
                        desc: e.desc,
                        id: $.zui.uuid(),
                        title: e.title
                    });
                    var date = new Date(e.year + '-' + e.month + '-' + e.day + ' 00:00:00');
                    date.setDate(date.getDate() + i - 1);
                    f.year = date.getFullYear();
                    f.month = date.getMonth() + 1;
                    f.day = date.getDate();
                    if (i == 1) {
                        f.start = e.start;
                    } else {
                        f.start = new Date(f.year + '-' + f.month + '-' + f.day + ' 00:00:00');
                    }
                    if (i == e.days) {
                        f.end = e.end;
                    } else {
                        f.end = new Date(f.year + '-' + f.month + '-' + f.day + ' 23:59:59');
                    }
                    that.events.push(f);
                    date = 0;
                    f = {};
                }
            } else {
                that.events.push(e);
            }
        });

        if (!silence) {
            that.sortEvents();
            that.display();
            that.callEvent('addEvents', {
                newEvents: events,
                data: that.data
            });
        }
    };
    /**
     * 获取指定的事件
     * @param {type} id
     * @returns {zui.calendar_L15.Calendar.prototype.getEvent.events|zui.calendar_L15.Calendar.events}
     */
    Calendar.prototype.getEvent = function (id) {
        var events = this.events;
        for (var i = 0; i < events.length; i++) {
            if (events[i].id == id) {
                return events[i];
            }
        }
        return null;
    };
    /**
     * 更新事件列表
     * @param {type} events
     * @returns {undefined}
     */
    Calendar.prototype.updateEvents = function (events) {
        var eventsParams = {
            data: this.data,
            changes: []
        },
        that = this;

        if($.isPlainObject(events)) {
            events = [events];
        }
        var event, chgs, eventParam;
        $.each(events, function (index, changes) {
            event = changes.event;
            chgs = changes.changes;
            eventParam = {
                event: event,
                changes: []
            };
            if (typeof event === STRING_TYPE_NAME) {
                event = that.getEvent(event);
            }
            if (event) {
                if ($.isPlainObject(chgs)) {
                    chgs = [chgs];
                }
                $.each(changes, function(idx, chge) {
                    if(that.callEvent('beforeChange', {
                            event: event,
                            change: chge.change,
                            to: chge.to,
                            from: event[chge.change]
                        })) {
                        eventParam.changes.push($.extend(true, {}, chge, {
                            from: event[chge.change]
                        }));
                        event[chge.change] = chge.to;
                    }
                });
            }
            eventsParams.changes.push(eventParam);
        });

        that.sortEvents();
        that.display();
        that.callEvent('change', eventsParams);
    };
    /**
     * 删除事件
     * @param {type} events 要删除的事件列表，为空的话就是清空所有事件
     * @returns {undefined}
     */
    Calendar.prototype.removeEvents = function (events) {
        if(!$.isArray(events)) {
            events = [events];
        }
        var id, event, idx, evts = this.events,
            that = this,
            removedEvents = [];
        if (!events) {
            this.events = [];
        } else {
            if (!$.isArray(events)) {
                events = [events];
            }
            $.each(events, function (index, value) {
                id = $.isPlainObject(value) ? value.id : value;
                idx = -1;
                for (var i = 0; i < evts.length; i++) {
                    if (evts[i].id == id) {
                        idx = i;
                        event = evts[i];
                        break;
                    }
                }
                if (idx >= 0 && that.callEvent('beforeRemoveEvent', {
                    event: event,
                    eventId: id,
                    data: that.data
                })) {
                    evts.splice(idx, 1);
                    removedEvents.push(event);
                }
            });
            that.sortEvents();
        }
        that.display();
        that.callEvent('removeEvents', {
            removedEvents: removedEvents,
            data: that.data
        });
    };

    Calendar.prototype.getOptions = function(options) {
        this.options = $.extend({}, Calendar.DEFAULTS, this.$.data(), options);
    };

    Calendar.prototype.getLang = function () {
        this.options.lang = $.zui.clientLang();
        this.lang = this.options.langs[this.options.lang] || this.options.langs[Calendar.DEFAULTS.lang];
    };
    /**
     * 显示指定日期
     * @param {type} view
     * @param {type} date
     * @returns {undefined}
     */
    Calendar.prototype.display = function (view, date) {
        var that = this;
        var viewType = typeof view;
        var dateType = typeof date;
        if (viewType === UNDEFINED_TYPE_NAME) {
            view = that.view;
        } else {
            that.view = view;
        }
        if (dateType === UNDEFINED_TYPE_NAME) {
            date = that.date;
        } else {
            that.date = date;
        }
        if (date === 'today') {
            date = new Date();
            that.date = date;
        }
        if (typeof date === STRING_TYPE_NAME) {
            date = new Date(date);
            that.date = date;
        }
        if (that.options.storage) {
            $.zui.store.pageSet(that.storeName,{
                date: date,
                view: view
            });
        }
        var eventPramas = {
            view: view,
            date: date
        };
        if (that.callEvent('beforeDisplay', eventPramas)) {
            switch (view) {
                case 'month':
                    that.displayMonth(date);
                    break;
            }
            that.callEvent('display', eventPramas);
        }
    };
    /**
     * 显示指定日期所在的月历
     * @param {type} date
     * @returns {undefined}
     */
    Calendar.prototype.displayMonth = function (date) {
        var that = this;
        date = date || that.date;
        var options = that.options,
                self = that,
                lang = that.lang,
                i,
                $view = '',
                $views = that.$views,
                firstDayOfMonth = getFirstDayOfMonth(date),
                lastDayOfMonth = getLastDayOfMonth(date),
                $e = that.$;
        var lengthOfView = 6;
        if (options.cacheView) {
            $view = self.$monthView;
        } else {
            var firstDayOfWeek = firstDayOfMonth.getDay();
            if (!firstDayOfWeek)
                firstDayOfWeek = 6;
            else
                firstDayOfWeek--;
            var lastDayOfWeek = lastDayOfMonth.getDay();
            if (lastDayOfWeek)
                lastDayOfWeek = 7 - lastDayOfWeek;
            lengthOfView = parseInt((lastDayOfMonth.getDate() + firstDayOfWeek + +lastDayOfWeek) / 7);
        }
        if (!$view.length) {
            $view = $('<div class="calendar-view month"><table class="table table-bordered"><thead><tr class="week-head"></tr></thead><tbody class="month-days"></tbody></table></div>');
            var $weekHead = $view.find('.week-head'),
                    $monthDays = $view.find('.month-days'),
                    $tr;
            for (i = 0; i < 7; i++) {
                $weekHead.append('<th>' + lang.weekNames[i] + '</th>');
            }

            for (i = 0; i < lengthOfView; i++) {
                $tr = $('<tr class="week-days"></tr>');
                for (var j = 0; j < 7; j++) {
                    //根据事件类型来决定显示方式
                    if (options.eventType == 'day') {
                        $tr.append('<td class="cell-day"><div class="day dayevent"><div class="heading"><span class="month"></span> <span class="number"></span></div><div class="content"><div class="events"></div></div></div></td>');
                    } else {
                        $tr.append('<td class="cell-day"><div class="day         "><div class="heading"><span class="month"></span> <span class="number"></span></div><div class="content"><div class="events"></div></div></div></td>');
                    }
                }
                $monthDays.append($tr);
            }
        }
        if (options.cacheView) {
            $views.append($view);
            self.$monthView = $view;
        } else {
            //清除日历显示
            $views.html('').append($view);
        }
        //美化显示效果
        var $monthDays = $views.find('.month-days');
        var h = $monthDays.find('td').first().height();
        var w = $monthDays.find('td').first().width();
        $monthDays.find('.heading').height(h - 2).width(w - 2);
        $monthDays.find('td').height(h);

        var $weeks = $view.find('.week-days'),
                $days = $view.find('.day'),
                $week,
                $day,
                $cell,
                year,
                day,
                month,
                today = new Date();
        var firstDay = getNearbyLastWeekDay(firstDayOfMonth),
                thisYear = date.getFullYear(),
                thisMonth = date.getMonth(),
                todayMonth = today.getMonth(),
                todayYear = today.getFullYear(),
                todayDate = today.getDate();
        var printDate = firstDay.clone().addDays(1).addMilliseconds(-1);
        if (options.showOtherMonth) {
            var lastDay = firstDay.clone().addDays(lengthOfView * 7).addMilliseconds(-1);
            var events = that.getEvents(firstDay, lastDay);
        } else {
            firstDay = firstDayOfMonth.clone();
            var lastDay = lastDayOfMonth.clone().addDays(1);
            var events = that.getEvents(firstDayOfMonth.addDays(-1), lastDay);
        }
        var calendars = that.calendars, printDateId, isFirstDayOfWeek, $event, cal, $dayEvents;

        $weeks.each(function (weekIdx) {
            $week = $(this);
            $week.find('.day').each(function (dayIndex) {
                isFirstDayOfWeek = dayIndex === 0;
                $day = $(this);
                $cell = $day.closest('.cell-day');
                year = printDate.getFullYear();
                day = printDate.getDate();
                month = printDate.getMonth();
                printDateId = printDate.toDateString();
                $day.attr('data-date', printDateId);
                $day.find('.heading > .number').text(day);

                $day.find('.heading > .month')
                        .toggle((weekIdx === 0 && dayIndex === 0) || day === 1)
                        .text(((month === 0 && day === 1) ? (lang.year.format(year) + ' ') : '') + lang.monthNames[month]);
                $cell.toggleClass('current-month', month === thisMonth);
                $cell.toggleClass('current', (day === todayDate && month === todayMonth && year === todayYear));
                $cell.toggleClass('past', printDate < today);
                $cell.toggleClass('future', printDate > today);
                $dayEvents = $day.find('.events').empty();
                if (options.showOtherMonth || (month === thisMonth)) {
                    var dayEvents = events[printDateId];
                    if (dayEvents) {
                        var eventsMap = dayEvents.events,
                                stripCount = 0, e;
                        for (i = 0; i <= dayEvents.maxPos; ++i) {
                            e = eventsMap[i];
                            if (!e || (e.placeholder && !isFirstDayOfWeek)) {
                                stripCount++;
                                continue;
                            }
                            $event = $('<div data-id="' + e.id + '" class="event" title="' + e.desc + '"><span class="time">' + e.start.format('hh:mm') + '</span> <span class="title">' + e.title + '</span></div>');
                            $event.find('.time').toggle(!e.allDay);
                            $event.data('event', e);
                            $event.attr('data-days', e.days);
                            if (e.color) {
                                $event.css({'background-color': e.color});
                            }
                            if (e.calendar) {
                                cal = calendars[e.calendar];
                                if (cal) {
                                    if (cal.presetColor) {
                                        $event.addClass('color-' + cal.color);
                                    } else {
                                        $event.css({'background-color': cal.color, color: cal.textColor});
                                    }
                                }
                            }
                            if (e.days) {
                                if (!e.placeholder) {
                                    $event.css('width', Math.min(7 - dayIndex, e.days) + '00%');
                                } else if (isFirstDayOfWeek) {
                                    $event.css('width', Math.min(7, e.days - e.holderPos) + '00%');
                                }
                            }
                            if (stripCount > 0) {
                                $event.css('margin-top', stripCount * 22);
                                stripCount = 0;
                            }
                            $dayEvents.append($event);
                            //美化显示效果
                            var h = $dayEvents.height();
                            var w = $dayEvents.parent().parent().width();
                            $dayEvents.width(w - 2);
                            var $td = $dayEvents.parent().parent();
                            $td.parent().parent().find('.heading').height(h - 2).width(w - 2);
                            $td.parent().height(h);
                        }
                    } else {
                        var h = 59;
                        var w = $dayEvents.parent().parent().width();
                        $dayEvents.width(w - 2);
                        var $td = $dayEvents.parent().parent();
                        $td.parent().parent().find('.heading').height(h - 2).width(w - 2);
                        $td.parent().height(h);
                    }
                    $td.parent().addClass('cell-day');
                } else {
                    $day.parent().removeClass('cell-day').html('');
                }
                printDate.addDays(1);
            });
        });

        if (options.withHeader) {
            that.$caption.text(lang.yearMonth.format(thisYear, thisMonth + 1, lang.monthNames[thisMonth]));
            that.$todayBtn.toggleClass('disabled', thisMonth === todayMonth);
        }

        if (options.dragThenDrop) {
            $view.find('.event').droppable({
                        target: $days,
                        container: $view,
                        flex: true,
                start: function () {
                    $e.addClass('event-dragging');
                },
                drop: function (e) {
                    var et = e.element.data('event'),
                        newDate = e.target.attr('data-date');
                    var startDate = et.start.clone();
                    if (startDate.toDateString() != newDate) {
                        newDate = new Date(newDate);
                        newDate.setHours(startDate.getHours());
                        newDate.setMinutes(startDate.getMinutes());
                        newDate.setSeconds(startDate.getSeconds());

                        if (self.callEvent('beforeChange', {
                                            event: et,
                                            change: 'start',
                                            to: newDate
                        })) {
                            var oldEnd = et.end.clone();
                            et.end.addMilliseconds(et.end.getTime() - startDate.getTime());
                            et.start = newDate;
                            that.display();
                            self.callEvent('change', {
                                data: self.data,
                                changes: [{
                                        event: et,
                                        changes: [{
                                                change: 'start',
                                                from: startDate,
                                                to: et.start
                                            }, {
                                                change: 'end',
                                                from: oldEnd,
                                                to: et.end
                                            }]
                                    }]
                            });
                        }
                    }
                },
                finish: function () {
                    $e.removeClass('event-dragging');
                }
            });
        }
    };
    /**
     * 获取指定日期范围内的所有事件
     * @param {type} start
     * @param {type} end
     * @returns {dayEvents}
     */
    Calendar.prototype.getEvents = function (start, end, eventtype) {
        var events = {};
        var calendars = this.calendars;
        var addEventToDay = function (day, event, position) {
            var dayId = day.toDateString();
            var dayEvents = events[dayId];
            if (!dayEvents) {
                dayEvents = {maxPos: -1, events: {}};
            }
            if (typeof position === 'undefined') {
                for (var i = 0; i < 100; ++i) {
                    if (!dayEvents.events[i]) {
                        position = i;
                        break;
                    }
                }
            }
            dayEvents.maxPos = Math.max(position, dayEvents.maxPos);
            dayEvents.events[position] = event;
            if (eventtype == 'all' || eventtype == event.eventtype) {
                events[dayId] = dayEvents;
            }
            return position;
        };
        if (!start && !end)
            return this.events;
        if (typeof (start) == OBJECT_TYPE_NAME) {
            end = start.end;
            eventtype = start.type;
            start = start.start;
        }
        if (!start)
            start = this.date.getFullYear() + '-' + (this.date.getMonth() + 1) + '-01';
        if (typeof (start) == STRING_TYPE_NAME)
            start = new Date(start).clearTime();
        if (typeof (end) == STRING_TYPE_NAME)
            end = new Date(end).clearTime();
        if (end == start || !end) {
            end = start.clone().addDays(this.date.getDaysInMonth()).addMilliseconds(-1);
        }
        if (!eventtype)
            eventtype = 'all';
        $.each(this.events, function (index, e) {
            if (e.start >= start && e.start <= end) {
                var position = addEventToDay(e.start, e);
                if (e.days > 1) {
                    var placeholder = $.extend({placeholder: true}, e);
                    everyDayTo(e.start.clone().addDays(1), e.end, function (thisDay, i) {
                        var et = e;
                        addEventToDay(thisDay.clone(), et);
                    });
                }
            }
        });
        return events;
    };

    Calendar.prototype.callEvent = function (name, params) {
        var result = this.$.callEvent(name + '.' + this.name, params, this);
        //有回传的参数
        if (result.result)
            params.result = result.result;
        return !(result.result !== undefined && (!result.result));
    };

    $.fn.calendar = function (option) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data(name);
            var options = typeof option == 'object' && option;

            if (!data)
                $this.data(name, (data = new Calendar(this, options)));

            if (typeof option == STRING_TYPE_NAME)
                data[option]();
        });
    };

    $.fn.calendar.Constructor = Calendar;
}(jQuery, window));
